<template>
  <dialog ref="dialogRef" class="bom-line-import-dialog" @cancel.prevent="close">
    <form method="dialog" class="dialog-shell" @submit.prevent>
      <header class="dialog-header">
        <h3 class="dialog-title">导入 BOM 行</h3>
        <button type="button" class="ui-close-btn" @click="close" aria-label="关闭">
          <svg viewBox="0 0 24 24" class="icon-x" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18" /><line x1="6" y1="6" x2="18" y2="18" /></svg>
        </button>
      </header>
      <section class="search-bar">
        <div class="search-box">
          <svg class="search-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8" /><path d="m21 21-4.35-4.35" /></svg>
          <input v-model="keyword" @keyup.enter="loadList(1)" placeholder="物料编码 / 名称" />
        </div>
        <select v-model="filterBomType" class="select">
          <option value="">类型(全部)</option>
          <option value="product">物料BOM</option>
          <option value="package">包装BOM</option>
        </select>
        <button type="button" class="btn primary" :disabled="loading" @click="loadList(1)">查询</button>
      </section>
      <section class="table-wrapper card" v-if="filtered.length">
        <table class="entry-table fancy">
          <thead>
            <tr>
              <th style="width:60px">选择</th>
              <th style="width:140px">名称</th>
              <th style="width:100px">BOM类型</th>
              <th style="width:140px">产品类型</th>
              <th style="width:100px">费用模式</th>
              <th style="width:110px">金额/单价</th>
              <th style="width:150px">创建时间</th>
              <th style="width:150px">修改时间</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="r in filtered" :key="r.id" @click="toggleRow(r)">
              <td>
                <input type="checkbox" :value="r.id" v-model="selectedIds" @click.stop="toggleRow(r)" />
              </td>
              <td class="strong" :title="r.costName">{{ r.costName }}</td>
              <td>{{ formatBomType(r.bomType) }}</td>
              <td>{{ r.productName }}</td>
              <td>{{ r.costMode==='fixed' ? '固定' : '计数' }}</td>
              <td class="num">{{ (r.unitPrice ?? r.fixedAmount ?? 0).toFixed(2) }}</td>
              <td>{{ formatDate(r.createdAt) }}</td>
              <td>{{ formatDate(r.updatedAt) }}</td>
            </tr>
          </tbody>
        </table>
        <div class="pagination-bar" v-if="total>0">
          <button type="button" class="btn ghost sm" :disabled="currentPage===1 || loading" @click="loadList(currentPage-1)">上一页</button>
          <span class="pager-info">第 {{ currentPage }} / {{ totalPages }} 页 (共 {{ total }} 条)</span>
          <button type="button" class="btn ghost sm" :disabled="currentPage===totalPages || loading" @click="loadList(currentPage+1)">下一页</button>
        </div>
      </section>
      <p v-else class="empty-tip" v-if="!loading && !error">暂无数据</p>
      <p v-if="error" class="empty-tip" style="color:#dc2626">{{ error }}</p>
      <div v-if="loading" class="empty-tip">加载中...</div>
      <footer class="dialog-actions">
        <button type="button" class="btn secondary" @click="close">取消</button>
        <button type="button" class="btn success" :disabled="!selectedIds.length" @click="confirmImport">导入选中 ({{ selectedIds.length }})</button>
      </footer>
    </form>
  </dialog>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import { fetchBomList } from '../../../services/bom';

interface BomEntryRow {
  id: string;
  costName: string;
  bomType: 'product' | 'package';
  productName: string;
  costMode: 'fixed' | 'count';
  fixedAmount?: number;
  unitPrice?: number;
  createdAt: number;
  updatedAt: number;
  raw?: any; // 保留原始记录便于扩展
}

const emit = defineEmits<{ (e:'import', lines:any[]):void }>();

const dialogRef = ref<HTMLDialogElement|null>(null);
const keyword = ref('');
const filterBomType = ref('');
const productTypeLimit = ref(''); // 打开时可指定按产品类型过滤

const records = ref<BomEntryRow[]>([]);
const loading = ref(false);
const error = ref('');
const total = ref(0); const currentPage = ref(1); const pageSize = ref(10); const totalPages = computed(()=> Math.max(1, Math.ceil(total.value / pageSize.value)));
const selectedIds = ref<string[]>([]);

async function loadList(page?: number){
  if(page) currentPage.value = page;
  loading.value = true; error.value='';
  try {
    const kw = keyword.value.trim();
    const data = await fetchBomList({ page: currentPage.value, pageSize: pageSize.value, invCode: kw, invName: kw, productType: productTypeLimit.value });
    total.value = data.total; pageSize.value = data.size; currentPage.value = data.current;
    records.value = (data.records||[]).map((r:any) => {
      const createdTs = r.createTime ? Date.parse(r.createTime.replace(/-/g,'/')) : Date.now();
      const updatedTs = r.updateTime ? Date.parse(r.updateTime.replace(/-/g,'/')) : createdTs;
      const feeAmountNum = typeof r.feeAmount === 'string' ? parseFloat(r.feeAmount) : (r.feeAmount || 0);
      return {
        id: r.id,
        costName: r.name || r.invName || '未命名',
        bomType: (r.bomType === 'package' ? 'package':'product'),
        productName: r.productType || '—',
        costMode: (r.feeModel === 'count' ? 'count':'fixed'),
        unitPrice: r.feeModel === 'count' ? feeAmountNum : undefined,
        fixedAmount: r.feeModel !== 'count' ? feeAmountNum : undefined,
        createdAt: createdTs,
        updatedAt: updatedTs,
        raw: r
      } as BomEntryRow;
    });
  } catch(e:any){ error.value = e.message || '加载失败'; }
  finally { loading.value = false; }
}

const filtered = computed(()=> records.value.filter(r => (!filterBomType.value || r.bomType===filterBomType.value)));

function open(limitProductType?: string){
  productTypeLimit.value = limitProductType || '';
  selectedIds.value = [];
  if(dialogRef.value && !dialogRef.value.open){ dialogRef.value.showModal(); }
  loadList(1);
}
function close(){ const el = dialogRef.value; if(el) el.close(); }
function toggleRow(r: BomEntryRow){ const idx = selectedIds.value.indexOf(r.id); if(idx>=0) selectedIds.value.splice(idx,1); else selectedIds.value.push(r.id); }

function confirmImport(){
  const selected = records.value.filter(r => selectedIds.value.includes(r.id));
  // 转换为产品编辑弹窗内部使用的 BOM 行结构
  const lines = selected.map((r, idx) => {
    // 属性映射：保留原始的 sort 值
    const attrObj: Record<string,string> = {};
    const attributeDefinitions: any[] = [];
    if(Array.isArray(r.raw?.attributes)){
      r.raw.attributes.forEach((a:any) => { 
        attrObj[a.propertyName] = String(a.propertyValue);
        attributeDefinitions.push({
          code: a.propertyName,
          name: a.propertyName,
          control: 'TextBox',
          sort: typeof a.sort === 'number' ? a.sort : undefined,
          propertyName: a.propertyName
        });
      });
    }
    const feeAmount = r.costMode==='count' ? (r.unitPrice||0) : (r.fixedAmount||0);
    return {
      id: r.raw?.id || '',
      _localId: `import-${r.id}-${Date.now()}-${idx}`,
      type: r.bomType==='package' ? 'packaging' : 'production',
      seq: 0,
      materialName: r.costName,
      materialCode: r.raw?.invCode || '',
      category: r.raw?.className || '',
      materialCategory: r.raw?.className || '',
      classId: r.raw?.classId || undefined,
      costName: r.costName,
      spec: '',
      qty: 1,
      unit: 'pcs',
      lossFactor: 1,
      unitCost: 0,
      attributes: attrObj,
      attributeDefinitions: attributeDefinitions.length > 0 ? attributeDefinitions : Object.keys(attrObj).map((k,i)=> ({ code:k, name:k, control:'TextBox', sort:i+1 })),
      attributeValues: attrObj,
      feeDetail: {
        mode: r.costMode,
        amount: feeAmount,
        quantity: r.costMode==='count' ? 1 : undefined,
        currency: 'CNY'
      }
    };
  });
  emit('import', lines);
  close();
}

function formatBomType(t:'product'|'package'){ return t==='package' ? '包装' : '物料'; }
function formatDate(ts:number){ const d = new Date(ts); return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')} ${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}`; }

defineExpose({ open, close });
</script>

<style scoped>
.bom-line-import-dialog { border:none; padding:0; border-radius:20px; width:960px; max-width:95vw; box-shadow:0 14px 38px -10px rgba(15,23,42,.35),0 6px 18px -6px rgba(15,23,42,.25); }
.bom-line-import-dialog::backdrop { background:rgba(15,23,42,.55); backdrop-filter:blur(6px); }
.dialog-shell { display:flex; flex-direction:column; max-height:calc(100dvh - 5rem); background:linear-gradient(145deg,#ffffff,#f8fafc 60%,#f1f5f9); }
.dialog-header { display:flex; justify-content:space-between; align-items:center; padding:1rem 1.3rem .85rem; border-bottom:1px solid #e2e8f0; }
.dialog-title { margin:0; font-size:19px; font-weight:700; }
.ui-close-btn { background:none; border:1px solid transparent; cursor:pointer; padding:.45rem; border-radius:12px; color:#64748b; transition:all .3s; }
.ui-close-btn:hover { background:linear-gradient(135deg,#fee2e2,#fecaca); color:#dc2626; transform:rotate(90deg); }
.search-bar { display:flex; gap:.75rem; align-items:center; flex-wrap:wrap; padding:.9rem 1.3rem .4rem; }
.search-box { display:flex; align-items:center; gap:.5rem; padding:.55rem .75rem; border:1px solid #cbd5e1; border-radius:12px; background:#fff; min-width:240px; transition:all .3s; }
.search-box:focus-within { border-color:#3b82f6; box-shadow:0 0 0 4px rgba(59,130,246,.18); }
.search-box input { border:none; outline:none; font-size:14px; flex:1; font-weight:500; }
.select { padding:.55rem .75rem; border:1px solid #cbd5e1; border-radius:12px; background:#fff; font-size:14px; font-weight:500; }
.select:focus { border-color:#3b82f6; box-shadow:0 0 0 4px rgba(59,130,246,.18); }
.btn { position:relative; cursor:pointer; border:1px solid transparent; padding:.6rem 1.1rem; border-radius:12px; font-size:14px; font-weight:600; display:inline-flex; align-items:center; gap:.45rem; transition:all .3s; }
.btn.primary { background:linear-gradient(135deg,#3b82f6,#2563eb); color:#fff; border-color:#2563eb; }
.btn.primary:hover { background:linear-gradient(135deg,#2563eb,#1d4ed8); transform:translateY(-2px); }
.btn.secondary { background:#ffffff; border:1px solid #d1d5db; color:#374151; }
.btn.secondary:hover { background:#f8fafc; border-color:#cbd5e1; transform:translateY(-2px); }
.btn.success { background:linear-gradient(135deg,#16a34a,#22c55e); color:#fff; border-color:#16a34a; }
.btn.success:hover { background:linear-gradient(135deg,#15803d,#16a34a); transform:translateY(-2px); }
.btn.ghost { background:rgba(255,255,255,.85); border:1px solid #e2e8f0; color:#374151; }
.btn.ghost.sm { padding:.45rem .75rem; font-size:12px; border-radius:10px; }
.table-wrapper.card { border:1px solid #e2e8f0; border-radius:16px; background:#fff; box-shadow:0 8px 25px -6px rgba(15,23,42,.1),0 3px 10px -2px rgba(15,23,42,.05); padding:.5rem .8rem .7rem; overflow:hidden; margin:0 1.3rem 1rem; }
.entry-table { width:100%; border-collapse:separate; border-spacing:0; font-size:13px; }
.entry-table thead th { background:linear-gradient(135deg,#f8fafc,#f1f5f9); font-weight:700; font-size:11px; letter-spacing:.05em; text-transform:uppercase; color:#475569; position:sticky; top:0; z-index:1; border-bottom:2px solid #e2e8f0; }
.entry-table th,.entry-table td { padding:.55rem .7rem; text-align:left; }
.entry-table tbody tr { cursor:pointer; transition:background .25s; }
.entry-table tbody tr:hover { background:linear-gradient(135deg,#f1f5f9,#e2e8f0); }
.entry-table td.strong { font-weight:600; }
.entry-table td.num { text-align:right; font-variant-numeric:tabular-nums; }
.pagination-bar { display:flex; align-items:center; gap:.6rem; justify-content:flex-end; padding:.4rem .4rem .1rem; }
.pager-info { font-size:11px; color:#475569; }
.empty-tip { color:#64748b; text-align:center; padding:2rem 0; font-size:14px; font-weight:500; }
.dialog-actions { display:flex; justify-content:flex-end; gap:.8rem; padding:.75rem 1.3rem .9rem; border-top:1px solid #e2e8f0; background:linear-gradient(135deg,#ffffff,#f8fafc); }
.icon-x { width:20px; height:20px; }
</style>
